package com.yiban.demo.Station.Controller;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.yiban.demo.Global.Configuration.WebsocketConfig;
import com.yiban.demo.LoginUser.Entity.LoginUserPO;
import com.yiban.demo.Global.Entity.ResponseEntity;
import com.yiban.demo.Station.Entity.StationOrderMessage;
import com.yiban.demo.Exception.MessageServiceException;
import com.yiban.demo.Order.Service.OrderService;
import com.yiban.demo.Util.JsonUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.validation.Validator;
import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

//默认多例，所以使用static+线程安全对象共享数据
//只做信息发送接收，实际复杂处理交给各个service实现类
@Service
@Slf4j
@ServerEndpoint(value = "/Station/PushSystem",configurator = WebsocketConfig.class)
public class PushStationServiceHandle {


    /**
     * sessions,onlineCount原子变量
     * orderService单例，线程安全
     */
    public static ConcurrentHashMap<Integer, Session> sessions = new ConcurrentHashMap<>();
    public static AtomicInteger onlineCount = new AtomicInteger(0);
   //由config注入
    public static OrderService orderService;
    public static Validator validator;
    public static long idleTimeOut;

    private final static String MESSAGE_CLASS_KEY = "MessageClass";
    private final static String ORDERID_KEY = "OrderId";
    private final static String DEVICEID_KEY = "DeviceId";




    //建立连接后获取握手后绑定的身份信息,将userId放入session（websocket）中
   @OnOpen
    public void open(Session session, EndpointConfig config){
        onlineCount.incrementAndGet();
        Integer userId = ((LoginUserPO) config.getUserProperties().get("user")).getUserId();
        session.getUserProperties().put("userId", userId);
        sessions.put(userId,session);
        session.setMaxIdleTimeout(idleTimeOut);
    }
    //关闭时通过session（websocket）中的userId移除在线的session
    @OnClose
    public void close(Session session){
        sessions.remove(session.getUserProperties().get("userId"));
        onlineCount.decrementAndGet();
    }


    //todo 就两个字段，不想写对应实体类了，等jdk15的recorded class出来再说吧
    /**
     * json示例
     * {
     *     "MessageClass":"DELIVERY",
     *     "OrderId":1252,
     *     "DeviceId":5646546
     * }
     */
    @OnMessage
    public void handleMessage(Session session,String message){
        try {
            HashMap<String,String> params = JsonUtil.defaultDeJsonify(HashMap.class, message);
            StationOrderMessage.StationOrderMessageClass messageClass = Optional.ofNullable(params.get(MESSAGE_CLASS_KEY))
                    .flatMap(StationOrderMessage.StationOrderMessageClass::getInstance)
                    .orElseThrow(() -> new MessageServiceException("不支持的信息类型"));
            //拓展这个，里面是个switch
            //若再多就用策略模式重构
            handleMessage(params,messageClass,session);

        } catch (JsonProcessingException e) {
            try {
                session.getBasicRemote().sendText("无法反序列化");
            } catch (IOException ioException) {
                ioException.printStackTrace();
            }
        }
    }
    @OnError
    public void handleError(Session session,Throwable throwable) throws JsonProcessingException {
        sendMessage(JsonUtil.defaultJsonify(ResponseEntity.Failure("发生异常"+throwable.getMessage())), session);
    }

    public void sendMessage(String msg,Session session){
        try {
            session.getBasicRemote().sendText(msg);
        } catch (IOException e) {
            log.error("发送消息出错", e);
            throw new MessageServiceException(e);
        }
    }

    public void sendMessage(String msg,Integer stationUserId){
        try {
            sessions.get(stationUserId).getBasicRemote().sendText(msg);
        } catch (IOException e) {
            log.error("发送消息出错：{}", e.getMessage());
        }
    }
    //根据userId广播
    public void BroadCastInfo(String msg, List<Integer> list){
        list.stream()
                .map(sessions::get)
                .filter(Objects::nonNull)
                .forEach(session -> sendMessage(msg,session));
    }
    public boolean isOnline(Integer userId){
        return sessions.get(userId) != null;
    }
    //从上到下开始运送，接收订单
    public void handleMessage(Map<String,String> params, StationOrderMessage.StationOrderMessageClass messageClass,Session session) throws JsonProcessingException {
        switch (messageClass) {
            case DELIVERY:
                handleDeliveryMessage(params, session);
                break;
            case RECEIVE:
                handleReceiveMessage(params, session);
                break;
            case IDLE:
                handleIdleMessage(session);
                break;
            default:
                handleDefaultMessage(session);
                break;
        }
    }
    private void handleDeliveryMessage(Map<String,String> params, Session session) throws JsonProcessingException {
        String response;
        String orderId = params.get(ORDERID_KEY);
        String deviceId = params.get(DEVICEID_KEY);
        if (deviceId == null){
            response =JsonUtil.defaultJsonify(ResponseEntity.Failure("缺少设备号"));
        }else if (orderId == null || !orderId.matches("[0-9]*") || orderService.deliveryOrder(Long.valueOf(orderId),deviceId)){
            response =JsonUtil.defaultJsonify(ResponseEntity.Failure("orderId异常,检测以下情况1，是否为空。2，是否不为数字。3，订单号不存在。4，订单状态不为配送"));
        }else {
            response = JsonUtil.defaultJsonify(ResponseEntity.Success(true));
        }
        sendMessage(response,session);
    }
    private void handleReceiveMessage(Map<String,String> params,Session session) throws JsonProcessingException {
        String response;
        String orderId = params.get("orderId");
        if (orderId == null || !orderId.matches("[0-9]*") || orderService.receiveOrder(Long.valueOf(orderId))) {
            response = JsonUtil.defaultJsonify(ResponseEntity.Failure("orderId异常,检测以下情况1，是否为空。2，是否不为数字。3，订单号不存在。4，订单状态不为等候"));
        }else {
            response = JsonUtil.defaultJsonify(ResponseEntity.Success(true));
        }
        sendMessage(response,session);
    }
    private void handleIdleMessage(Session session) throws JsonProcessingException {
        sendMessage(JsonUtil.defaultJsonify(ResponseEntity.Success("ping")), session);
    }

    private void handleDefaultMessage(Session session) throws JsonProcessingException {
        sendMessage(JsonUtil.defaultJsonify(ResponseEntity.Failure("暂不支持的类型")), session);
    }



}
